import pulp
import numpy as np
import matplotlib.pyplot as plt

# 设置中文显示
plt.rcParams['font.sans-serif'] = ['SimHei']
plt.rcParams['axes.unicode_minus'] = False
# 创建线性规划问题
prob = pulp.LpProblem("综合优化饮食问题", pulp.LpMinimize)

# 食物数量变量
food_vars = pulp.LpVariable.dicts("食物", range(1, 13), lowBound=0, upBound=2, cat='Integer')

# 目标函数系数和食物价格
objective_coeffs = {1: 0.43, 2: 0.1, 4: 0.26, 5: 0.32, 6: 0.01, 7: 0.5, 9: 0.29, 10: 0.99}
food_prices = [6, 1.5, 1.5, 3, 8, 1, 3, 1, 3, 7, 1, 0.5]

# 权重设置（可以根据需求调整）
weight_aas = 0.5
weight_price = 0.5

# 目标函数
prob += weight_price * pulp.lpSum([food_prices[i-1] * food_vars[i] for i in range(1, 13)]) - \
        weight_aas * pulp.lpSum([objective_coeffs[i] * food_vars[i] for i in objective_coeffs]), "综合目标函数"

# 可以半份
food_vars[3].upBound = 1
food_vars[7].upBound = 1
food_vars[9].upBound = 1
food_vars[10].upBound = 1

# 约束条件
prob += 0.25 * pulp.lpSum([174.50 * food_vars[1], 33.90 * food_vars[2], 135.00 * food_vars[3]]) <= 0.35 * 2000, "早餐"
prob += 0.30 * pulp.lpSum([87.25 * food_vars[4], 174.50 * food_vars[5]]) <= 0.40 * 2000, "午餐"
prob += 0.30 * pulp.lpSum([66.00 * food_vars[7], 91.00 * food_vars[8], 11.50 * food_vars[9]]) <= 0.40 * 2000, "晚餐"
prob += 0.10 * pulp.lpSum([5.20 * food_vars[1], 1.18 * food_vars[2], 4.69 * food_vars[3], 2.60 * food_vars[4], 5.20 * food_vars[5],
                          0.50 * food_vars[6], 4.50 * food_vars[7], 1.40 * food_vars[8], 0.90 * food_vars[9], 9.90 * food_vars[10]]) <= 0.15 * 2000, "蛋白质"
prob += 0.20 * pulp.lpSum([0.55 * food_vars[1], 0.49 * food_vars[2], 5.06 * food_vars[3], 0.28 * food_vars[4], 0.55 * food_vars[5],
                          0.20 * food_vars[6], 0.60 * food_vars[7], 0.20 * food_vars[8], 0.25 * food_vars[9], 0.55 * food_vars[10]]) <= 0.30 * 2000, "脂肪"
prob += 0.50 * pulp.lpSum([37.15 * food_vars[1], 6.19 * food_vars[2], 17.44 * food_vars[3], 18.58 * food_vars[4], 37.15 * food_vars[5],
                          9.90 * food_vars[6], 10.80 * food_vars[7], 20.80 * food_vars[8], 1.35 * food_vars[9], 12.30 * food_vars[11], 38.60 * food_vars[12]]) <= 0.65 * 2000, "碳水化合物"
prob += 1800 <= pulp.lpSum([174.50 * food_vars[1], 33.90 * food_vars[2], 135.00 * food_vars[3], 87.25 * food_vars[4], 174.50 * food_vars[5],
                          43.00 * food_vars[6], 66.00 * food_vars[7], 91.00 * food_vars[8], 11.50 * food_vars[9], 44.00 * food_vars[10], 52.00 * food_vars[11], 173.00 * food_vars[12]]), "最低能量"
prob += pulp.lpSum(food_vars) >= 12, "最低食物数量"

# 定义 w1 和 w2 的取值范围
w1_values = np.linspace(0, 1, 20)

w2_values = np.linspace(0, 1, 20)

# 存储最优值的列表
optimal_values = []

# 遍历所有 w1 和 w2 组合
for w1 in w1_values:
    for w2 in w2_values:
        # 创建线性规划问题
        prob = pulp.LpProblem("综合优化饮食问题", pulp.LpMinimize)

        # 目标函数
        prob += w1 * pulp.lpSum([food_prices[i-1] * food_vars[i] for i in range(1, 13)]) - \
                w2 * pulp.lpSum([objective_coeffs[i] * food_vars[i] for i in objective_coeffs]), "综合目标函数"

        # 添加约束
        prob += 0.25 * pulp.lpSum([174.50 * food_vars[1], 33.90 * food_vars[2], 135.00 * food_vars[3]]) <= 0.35 * 2000, "早餐"
        prob += 0.30 * pulp.lpSum([87.25 * food_vars[4], 174.50 * food_vars[5]]) <= 0.40 * 2000, "午餐"
        prob += 0.30 * pulp.lpSum([66.00 * food_vars[7], 91.00 * food_vars[8], 11.50 * food_vars[9]]) <= 0.40 * 2000, "晚餐"
        prob += 0.10 * pulp.lpSum([5.20 * food_vars[1], 1.18 * food_vars[2], 4.69 * food_vars[3], 2.60 * food_vars[4], 5.20 * food_vars[5],
                                  0.50 * food_vars[6], 4.50 * food_vars[7], 1.40 * food_vars[8], 0.90 * food_vars[9], 9.90 * food_vars[10]]) <= 0.15 * 2000, "蛋白质"
        prob += 0.20 * pulp.lpSum([0.55 * food_vars[1], 0.49 * food_vars[2], 5.06 * food_vars[3], 0.28 * food_vars[4], 0.55 * food_vars[5],
                                  0.20 * food_vars[6], 0.60 * food_vars[7], 0.20 * food_vars[8], 0.25 * food_vars[9], 0.55 * food_vars[10]]) <= 0.30 * 2000, "脂肪"
        prob += 0.50 * pulp.lpSum([37.15 * food_vars[1], 6.19 * food_vars[2], 17.44 * food_vars[3], 18.58 * food_vars[4], 37.15 * food_vars[5],
                                  9.90 * food_vars[6], 10.80 * food_vars[7], 20.80 * food_vars[8], 1.35 * food_vars[9], 12.30 * food_vars[11], 38.60 * food_vars[12]]) <= 0.65 * 2000, "碳水化合物"
        prob += 1800 <= pulp.lpSum([174.50 * food_vars[1], 33.90 * food_vars[2], 135.00 * food_vars[3], 87.25 * food_vars[4], 174.50 * food_vars[5],
                                  43.00 * food_vars[6], 66.00 * food_vars[7], 91.00 * food_vars[8], 11.50 * food_vars[9], 44.00 * food_vars[10], 52.00 * food_vars[11], 173.00 * food_vars[12]]), "最低能量"
        prob += pulp.lpSum(food_vars) >= 12, "最低食物数量"

        # 求解问题
        prob.solve()

        # 记录最优值
        optimal_values.append(pulp.value(prob.objective))

# 将最优值转换成二维数组
optimal_values = np.array(optimal_values).reshape(len(w1_values), len(w2_values))

# 绘制图像
plt.figure(figsize=(8, 6), dpi=200)
plt.contourf(w1_values, w2_values, optimal_values, cmap='viridis')
plt.colorbar(label='目标函数最优值')
plt.xlabel('w1')
plt.ylabel('w2')
plt.title('不同权重下的最优解-女生')
plt.grid(True)
plt.savefig('综合评价-女.png', dpi=200)
plt.show()

